package com.sjy.ylxt.utils;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.nio.charset.StandardCharsets;
import java.math.BigInteger;

public class HashUtil {

    /**
     * 对输入字符串进行哈希计算。
     *
     * @param input  要哈希的字符串
     * @param algorithm 使用的哈希算法名称（例如 "MD5", "SHA-1", "SHA-256"）
     * @param charsetName 字符串的字符集编码（例如 "UTF-8"）
     * @param salt 用于增加安全性的盐（可选）
     * @return 哈希后的16进制字符串
     */
    public static String hash(String input, String algorithm, String charsetName, byte[] salt) {
        try {
            MessageDigest md = MessageDigest.getInstance(algorithm);
            if (salt != null && salt.length > 0) {
                md.update(salt); // 在消息摘要中加入盐
            }
            byte[] messageDigest = md.digest(input.getBytes(charsetName));

            BigInteger no = new BigInteger(1, messageDigest);
            String hashtext = no.toString(16);

            // 确保长度正确，前面补0
            while (hashtext.length() < 32) { // 32是MD5的长度，其他算法可能不同
                hashtext = "0" + hashtext;
            }

            return hashtext;
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("Algorithm not found: " + algorithm, e);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 生成随机盐
     *
     * @param numBytes 盐的字节数
     * @return 随机生成的盐
     */
    public static byte[] generateSalt(int numBytes) {
        byte[] salt = new byte[numBytes];
        java.util.Random random = new java.util.Random();
        random.nextBytes(salt);
        return salt;
    }

    /**
     * 验证提供的密码是否与存储的哈希值匹配。
     *
     * @param providedPassword 用户提供的密码
     * @param storedHash 存储的哈希值
     * @param salt 用于哈希的盐
     * @param algorithm 使用的哈希算法名称
     * @param charsetName 字符串的字符集编码
     * @return 如果提供的密码匹配存储的哈希值，则返回true；否则返回false
     */
    public static boolean verifyPassword(String providedPassword, String storedHash, byte[] salt, String algorithm, String charsetName) {
        String newHash = hash(providedPassword, algorithm, charsetName, salt);
        return newHash.equals(storedHash);
    }

    /**
     * 测试方法
     */
    public static void main(String[] args) {
        String password = "your_password_here"; // 要加密的字符串
        byte[] salt = generateSalt(16); // 生成16字节的随机盐

        // 创建哈希并存储
        String hashedPassword = hash(password, "SHA-256", StandardCharsets.UTF_8.name(), salt);
        System.out.println("Original: " + password);
        System.out.println("SHA-256 with Salt: " + hashedPassword);

        // 验证密码
        String providedPassword = "your_password_here"; // 用户提供的密码
        boolean isVerified = verifyPassword(providedPassword, hashedPassword, salt, "SHA-256", StandardCharsets.UTF_8.name());
        System.out.println("Password verified: " + isVerified);

        // 尝试使用错误的密码
        String wrongPassword = "wrong_password";
        boolean isWrongVerified = verifyPassword(wrongPassword, hashedPassword, salt, "SHA-256", StandardCharsets.UTF_8.name());
        System.out.println("Wrong password verified: " + isWrongVerified);
    }
}